/*
 *  Copyright (C) 2012 Компания ВИТ. web: http://diasled.ru Е-mail:  vit@diasled.ru
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package ru.apertum.diasled.common;

import java.awt.Image;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.swing.ImageIcon;
import org.apache.log4j.Logger;
import ru.apertum.diasled.cfg.MyPoint;

/**
 *
 * @author Evgeniy Egorov , Aperum Projects
 */
public class Uses {

    public static final String DB_URL = "jdbc:h2:~/H2/DiasledDB";
    //public static final String DB_URL = "jdbc:derby:DiasledDB;create=true;user=diasled;password=diasled";
    //public static final String DB_URL = "jdbc:mysql:mxj:///DiasledDBm?server.initialize-user=true&amp;createDatabaseIfNotExist=true&amp;server.basedir=DiaDB&amp;server.datadir=DiaDB/data&amp;user=root&amp;password=root";
    // Ключи выполнения программы
    public static final String KEY_DEBUG = "DEBUG";
    public static final String KEY_INFO = "INFO";
    public static final String KEY_DEMO = "DEMO";
    /**
     * Режим отладки
     */
    public static boolean isDebug = false;
    /**
     * Режим отладки
     */
    public static boolean isDemo = false;
    /**
     * Формат даты
     */
    public static final String DATE_FORMAT = "dd.MM.yyyy HH:mm:ss";
    /**
     * Формат даты без времени
     */
    public static final String DATE_FORMAT_ONLY = "dd.MM.yyyy";
    /**
     * Формат даты без времени, с годом и месяц прописью
     */
    public static final String DATE_FORMAT_FULL = "dd MMMM yyyy";
    /**
     * Формат даты.
     */
    public final static DateFormat format_HH_mm = new SimpleDateFormat("HH:mm");
    /**
     * Формат даты.
     */
    public final static DateFormat format_HH_mm_ss = new SimpleDateFormat("HH:mm:ss");
    /**
     * Формат даты.
     */
    public final static DateFormat format_dd_MM_yyyy = new SimpleDateFormat(DATE_FORMAT_ONLY);
    /**
     * Формат даты. dd_MMMM_yyyy
     */
    public final static DateFormat format_dd_MMMM_yyyy = new SimpleDateFormat(DATE_FORMAT_FULL);
    /**
     * Формат даты.
     */
    public final static DateFormat format_dd_MM_yyyy_time = new SimpleDateFormat(DATE_FORMAT);
    /**
     * Формат даты.
     */
    public final static DateFormat format_dd_MMMM = new SimpleDateFormat("dd MMMM");
    /**
     * Формат даты./2009-01-26 16:10:41
     */
    public final static DateFormat format_for_rep = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    /**
     * Формат даты./2009-01-26 16:10
     */
    public final static DateFormat format_for_trans = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    /**
     * Формат даты./2009 январь 26 16:10:41
     */
    public final static DateFormat format_for_label = new SimpleDateFormat("dd MMMM HH.mm.ss");

    /**
     *  Собственно, логер лог4Ж
     */
    public final static class Log extends Object {

        public Logger logger;// = Logger.getLogger("diasled.file");//**.file.info.trace
    };
    /**
     * Пользуемся этой константой для работы с логом
     */
    public static final Log log = new Log();

    /**
     * Определение политики логирования.
     * @param args параметры командной строки
     * @return вести отладку или нет.
     */
    public static boolean setLogining(String[] args) {
        boolean isDebugin = false;
        Uses.log.logger = Logger.getLogger("diasled.file.info.trace");

        //бежим по параметрам, смотрим, выполняем что надо
        /*
        for (int i = 0; i < args.length; i++) {
        // ключ, отвечающий за логирование
        if (Uses.KEY_DEBUG.equalsIgnoreCase(args[i])) {
        Uses.log.logger = Logger.getLogger("diasled.file.info.trace");
        isDebugin = true;
        }
        
        if (Uses.KEY_DEMO.equalsIgnoreCase(args[i])) {
        isDemo = true;
        }
        }
         * 
         */
        Uses.log.logger.info("СТАРТ ЛОГИРОВАНИЯ. Логгер: " + Uses.log.logger.getName());
        return isDebugin;
    }

    /**
     * Этот класс исключения использовать для програмной генерации исклюсений.
     * Записывает StackTrace и  само исключение в лог.
     * Это исключение не показывает диологовое окно при возникновении ошибки
     * Используется в системе статистики и отчетов.
     * @author egorov
     */
    public static class SilentException extends RuntimeException {

        public SilentException(String textException) {
            super(textException);
            log.logger.error("Error!", this);
        }
    }

    public static class ClientException extends Exception {

        public ClientException(String textException) {
            super(textException);
            log.logger.error("Error!", this);
        }

        public ClientException(Exception ex) {
            super(ex);
            log.logger.error("Error!", ex);
        }

        public ClientException(String textException, Exception ex) {
            super(textException, ex);
            log.logger.error("Error!", ex);
        }
    }

    /**
     * Для чтения байт из потока.
     * @param stream из него читаем
     * @return byte[] результат
     * @throws java.io.IOException
     * @see readSocketInputStream(InputStream stream)
     */
    public static byte[] readInputStream(InputStream stream) throws IOException {
        final byte[] result;
        final DataInputStream dis = new DataInputStream(stream);
        result = new byte[stream.available()];
        dis.readFully(result);
        return result;
    }

    /**
     * сегодняшняя ли это дата
     * @param date
     * @return 
     */
    public static boolean isNow(Date date) {
        return isSameDates(date, new Date());
    }

    /**
     * одинаковые ли даты с точностью до дня
     * @param date1
     * @param date2
     * @return 
     */
    public static boolean isSameDates(Date date1, Date date2) {
        final GregorianCalendar gc1 = new GregorianCalendar();
        gc1.setTime(date1);
        final GregorianCalendar gc2 = new GregorianCalendar();
        gc2.setTime(date2);
        return (gc1.get(GregorianCalendar.DAY_OF_YEAR) == gc2.get(GregorianCalendar.DAY_OF_YEAR)
                && gc1.get(GregorianCalendar.YEAR) == gc2.get(GregorianCalendar.YEAR));
    }

    /**
     *  грузит картинку из файла или ресурсов.
     *  Если Параметр пустой, то возвращает null.
     * @param o Объект для загрузки ресурса из jar, чаще всего класс в котором понадобилась эта картинка.
     * @param resourceName путь к ресурсу или файлу картинки. Может быть пустым.
     * @return
     */
    public static Image loadImage(Object o, String resourceName) {
        if ("".equals(resourceName)) {
            return null;
        } else {
            final DataInputStream inStream;
            File f = new File(resourceName);
            if (f.exists()) {
                return new ImageIcon(resourceName).getImage();
            } else {
                inStream = new DataInputStream(o.getClass().getResourceAsStream(resourceName));
            }
            byte[] b = null;
            try {
                b = new byte[inStream.available()];
                inStream.readFully(b);
                inStream.close();
            } catch (IOException ex) {
                System.err.println(ex);
            }
            return new ImageIcon(b).getImage();
        }
    }

    private static class Vect {

        public Vect(MyPoint p0, MyPoint p1) {
            x = p1.x - p0.x;
            y = p1.y - p0.y;
        }
        public double x, y;
    }

    private static double scalarMultiply(Vect v0, Vect v1) {
        return v0.x * v1.x + v0.y * v1.y;
    }

    public static double distancePtoP(MyPoint p0, MyPoint p1) {
        return Math.hypot(p0.x - p1.x, p0.y - p1.y);
    }

    public static double distancePointToSegment(MyPoint p, MyPoint p0, MyPoint p1) {
        final Vect v = new Vect(p0, p1);
        final Vect w = new Vect(p0, p);
        final double c1, c2;
        if ((c1 = scalarMultiply(w, v)) <= 0) {
            return distancePtoP(p, p0);
        }
        if ((c2 = scalarMultiply(v, v)) <= c1) {
            return distancePtoP(p, p1);
        }
        final double b = c1 / c2;
        final MyPoint pb = new MyPoint((int) (p0.x + b * v.x), (int) (p0.y + b * v.y));
        return distancePtoP(p, pb);
    }
}
